#!/usr/bin/env ruby
# RedBook is a command-line personal logger and time tracker written in Ruby.
#
# Web Site:: http://redbook.h3rald.com
# Author::    Fabio Cevasco (mailto:h3rald@h3rald.com)
# Copyright:: Copyright (c) 2007-2008 Fabio Cevasco
# License::   BSD
class RedBook

	VERSION = "1.0.0"
	NAME = "RedBook"
	WELCOME = "#{NAME} v#{VERSION} - Copyright (c) 2007-#{Time.now.strftime("%Y")}, Fabio Cevasco"
	MODE = 'exe' # source/gem/exe

	# Load required libraries
	try_to "load required libraries" do
		require 'rubyscript2exe' if RedBook::MODE == 'exe'
		require 'ftools'
		require 'yaml'
		require 'chronic'
		require 'active_support'
		require 'observer'
		require 'rawline'
		require 'iconv'

		if PLATFORM.match(/win32/i) then
			begin
				require 'win32console'
				COLORS_ENABLED = true
			rescue
				COLORS_ENABLED = false
			end
		else
			COLORS_ENABLED = true
		end
	end

	# Set HOME directories
	if MODE == 'exe' then
		if RUBYSCRIPT2EXE.is_compiling? then
			HOME = File.dirname(File.expand_path(__FILE__))
			EXEHOME = HOME
		else
			HOME = RUBYSCRIPT2EXE.appdir.gsub('\\','/')
			EXEHOME = RUBYSCRIPT2EXE.exedir.gsub('\\','/')
		end
	else
		HOME = File.dirname(File.expand_path(__FILE__))
		EXEHOME = HOME
	end
	USERHOME = PLATFORM.match(/win32/i) ? ENV['HOMEPATH'] : ENV['HOME']

	def initialize
		default_config
		load_config
		load_core
		start_interface
		load_plugins
		load_emitters
	end

	def try_to(action="")
		if block_given? then
			begin
				yield
			rescue Exception => e
				if action == "" then
					message = "ERROR:"
				else
					message = "Error when trying to #{action}:"
				end
				$stderr.puts message
				$stderr.puts e.message
			end
		end
	end

	private

	def load_config
		try_to "load configuration file" do
			require "#{HOME}/redbookrc.rb"
			require File.exist?("#{USERHOME}/redbookrc.rb") ? "#{ENV['HOME']}/redbookrc.rb" : "#{EXEHOME}/redbookrc.rb"
		end
	end

	def load_core
		try_to "load core classes" do
			require "#{HOME}/redbook/core_extensions.rb"
			require "#{HOME}/redbook/messenger.rb"
			require "#{HOME}/redbook/utils.rb"
			require "#{HOME}/redbook/callback_collection.rb" 
			require "#{HOME}/redbook/timecalc.rb"
			require "#{HOME}/parsers/parser.rb"
			require "#{HOME}/redbook/core.rb"
			RedBook::include RedBook::Messenger
			RedBook::include RedBook::Utils
		end
	end

	def start_interface
		interface = @config[:interface].camelcase
		load_files(@config[:interface], @config[:interface_dirs], :interface)
		instance_eval "#{interface}.start"
	end

	def load_plugins
		load_files(@config[:plugins], @config[:plugin_dirs], :plugin)
	end

	def load_emitters
		load_files(@config[:emitters], @config[:emitter_dirs], :emitter)
	end

	def load_files(file_list, dir_list, type)
		obj = type.to_s
		objs = obj.pluralize 
		debug "Loading #{objs}"
		require "#{HOME}/lib/#{objs}/#{obj}.rb"
		try_to "load #{obj}" do
			@config[:"#{objs}"].each do |o|
				found = false
				unless found then
					@config[:"#{obj}_dirs"].each do |d|
						require "#{d}#{o}_#{obj}.rb"
						found = true
					end
				end
				error "#{obj.capitalize} '#{o.camelcase}' not found" unless found
			end
		end
	end

	def default_config
		@config[:interface_dirs] = ["#{HOME}/lib/interfaces/"]
		@config[:renderer_dirs] = ["#{HOME}/lib/renderers/"]
		@config[:plugin_dirs] = ["#{HOME}/lib/plugins/"]
		@config[:interface] = 'console'
		@config[:emitters] = ['console', 'text', 'yaml', 'xml', 'csv']
		@config[:plugins] = ['twitter', 'tracker', 'archiver', 'csv']
		@config[:debug] = false
		@config[:prompt] = '"redbook@#{@logger.alias}[#{@logger.current_dataset.length}/#{@logger.current_log.length}]#> "'
		@config[:shortcuts] = {
			:test 	=> ":use test",
			:def 		=> ":use default",
			:today	=> ":select :plain :from today",
			:cf			=> ":log Coffee Break :with _break",
			:lunch 	=> ":log Lunch Break :with _break",
			:work 	=> ":log Working Day",
			:mail 	=> ":log Checking/writing emails :with mail",
			:ph 		=> ":log Phone Call :with call",
			:b 			=> ":backup",
			:a 			=> ":archive",
			:"\t" 	=> ":finish",
			:"\e"		=> ":quit",
			:"\s" 	=> ":clear",
			:"5" 		=> ":select :plain :last 5",
			:"10" 	=> ":select :plain :last 10",
			:pend 	=> ":select :pending :from today at 8 am",
			:done 	=> ":select :completed :from today at 8 am",
			:plain 	=> ":select :plain :from today at 8 am",
			:int 		=> ":int",
			:spent 	=> ":timespent",
		}
		@config[:time_format] = "%a %b %d %Y - %I:%M:%S %p"
		@config[:backups_folder] = ""
		@config[:archives_folder] = ""
		@config[:default_output_file] = "log.txt"	
		@config[:twitter] = {
			:username => "",
			:password => "",
		}
		@config[:charsets] = {
			:input 	=> "CP437",
			:output => "UTF-8",
			:log		=> "UTF-8"
		}
		@config[:csv] = {
			:separator 	=> ",",
			:duration_time_unit => "seconds",
			:msproject_fields		=> false,
			:headers 		=> {
				:type 	  		=> "Type",
				:value 	  		=> "value",
				:message  		=> "Message",
				:start_date		=> "Start Date",
				:end_date			=> "End Date",
				:duration			=> "Duration",
				:tags					=> "Tags"
			}	
		}
		@config[:logs] = ["log.yml", "test.yml"]
		@config[:macros] = {
			:send 			=> ":log <:message> :with _twitter _to:<:to>",
			:status			=> ":log <:message> :with _twitter",
			:break			=> ":log <:message> :with _break",
			:conc				=> ":log <:message> :with _concurrent",
			:int				=> ":log Interruption :with interruption",
			:timespent	=> ":select :duration :from today at 8 am"
		}
	end

end
